[JavaScript]Ajvでschema検証テストをする際の注意点
SBJソリューション部のserinaです。
PostmanでAjvライブラリを使用してschemaを検証するテストを書いたのですが、意外とスムーズに行かなかったので注意点、というか、はまった内容をまとめます。
やりたかったこと
OpenAPI仕様に書かれているschemaをそのまま貼り付けて、schema検証テストに使用したかったです。
はまったところ
type: integer
の際にnullが許容されずエラーになる
format: "int64"
を書くとエラーになります。
Ajvはデフォルトではこのformatを認識してくれないようです。
解決方法
ajvのaddFormatを使用して設定します。
const Ajv = require('ajv');
ajv.addFormat('int64', true);
addFormatにvalidateを記載できるのですがバグなのか機能していないため、ひとまずこれでエラー回避するようにしています。
もっと良い書き方があれば教えてほしいです。
"nullable": true
が認識されない
Ajvで schemaに "nullable": true
と記載しているのに、このようなエラーが出てnullが許容されなかったです。
Validation errors: data.XXXX should be integer
解決方法
newするときにnullを許容する設定を行います。
const Ajv = require('ajv');
const ajv = new Ajv({nullable: true});
$refとallOfを取り除いたschemaが必要
ymlファイルで作成していたため、jsonファイルに変換して貼り付ける必要がありました。
しかし、$refやallOfを使用していたためそのままではテストがうまくいかず、純粋なschemaに変換する必要がありました。
解決方法
以下、2つのjsライブラリを使用して変換後のファイルを生成し、そのファイルのschemaを使用することにしました。
また、今回は詳しく書きませんが、このファイルをdockerで定期的に実行することで常に最新のjsonファイルが作成されるようにもしました。
jsファイル
const SwaggerParser = require('@apidevtools/swagger-parser');
const mergeAllOf = require('json-schema-merge-allof');
const fs = require('fs');
/**
* $refを取り除き、allOfを展開してファイル出力
* @param {*} inputFilePath
* @param {*} outputFilePath
*/
async function processOpenAPISchema(inputFilePath, outputFilePath) {
try {
// $refをなくす
const api = await SwaggerParser.dereference(inputFilePath);
// allOfを展開し、順序を保ったスキーマを作成する
function processSchema(schema) {
if (schema && typeof schema === 'object') {
if (schema.allOf) {
schema = mergeAllOf(schema, { resolvers: {} });
}
for (const key in schema) {
schema[key] = processSchema(schema[key]);
}
if (schema.type === 'object') {
return {
type: schema.type,
properties: schema.properties,
required: schema.required,
};
}
}
return schema;
}
// $refをなくしたOpenAPIからallOfもなくす
const processedApi = processSchema(api);
// 結果をファイルに書き出す
fs.writeFileSync(outputFilePath, JSON.stringify(processedApi, null, 2));
console.log('Processed OpenAPI schema written to', outputFilePath);
} catch (err) {
console.error('Error processing OpenAPI schema:', err);
}
}
processOpenAPISchema('index.yml', 'openapi-without-allOf-and-ref.json');
実行方法
node main.js
最後に
ジェネレータ生成のライブラリはいくつかあったので、json schemaを生成するライブラリに辿り着くのに結構時間をかけてしまいました。